﻿/************************************************************************
 * SMLib - State Model Library
 * Copyright (C) 2012-2013 Ali Khalili (khalili_DOT_ir_@SIGN_gmail_DOT_com)
 * **********************************************************************
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License (LGPL) published 
 * by the Free Software Foundation; either version 2.1 of the License, or (at your
 * option) any later version. This program is distributed without any
 * warranty. See the GNU Lesser General Public License for more details. 
 * ***********************************************************************
 * File         :     SMLib\Automata\Base\WordsLexicoComparer.cs
 * Description  :     Providing Lixicographical comparison
 * Change log   :     -Oct 2013: Initial version
 * To Do        :
 ************************************************************************/
using System;
using System.Collections.Generic;
using System.Collections;

namespace SMLib.Automata.Base
{
    /// <summary>
    /// Providing Lixicographical comparison
    /// </summary>
    public class WordsLexicoComparer : IComparer
    {
        /// <summary>
        /// The current alphabet to be used in comparison
        /// </summary>
        Alphabet CurrentAlphabet;

        /// <summary>
        /// Constructor
        /// </summary>
        /// <param name="alphabet">the alphabet to be used for comparison</param>
        public WordsLexicoComparer(Alphabet alphabet)
        {
            CurrentAlphabet = alphabet;
            if (CurrentAlphabet == null)
                throw new Exception("Currently using alphabet is not set!");
        }

        #region IComparer Members
        /// <summary>
        /// Compare two words
        /// </summary>
        /// <param name="x">first word</param>
        /// <param name="y">other word</param>
        /// <returns>result of comparison (based on IComparer convention)</returns>
        public int Compare(object x, object y)
        {
            if (!(x is Word))
                throw new Exception("Type " + x.GetType().ToString() + " is not comparable with Word");
            else if (!(y is Word))
                throw new Exception("Type " + y.GetType().ToString() + " is not comparable with Word");


            Word w1 = (Word)x;
            Word w2 = (Word)y;
            //* 1-based on the length
            if (w1.Length < w2.Length)
                return -1;
            else if (w1.Length > w2.Length)
                return 1;
            //* 2-based on order of symbols
            for (int i = 0; i < Math.Min(w1.Length, w2.Length); i++)
            {
                int r1 = CurrentAlphabet.Rank(w1[i]);
                int r2 = CurrentAlphabet.Rank(w2[i]);
                if (r1 == -1 || r2 == -1)
                {
                    throw new Exception("Oops! Symbol not found in alphabet!");
                }
                if (r1 < r2)
                    return -1;
                else if (r1 > r2)
                    return 1;
            }

            return 0;

        }

        #endregion
    }
}
